﻿using System;
using System.Configuration;
using System.IO;
using System.Net;
using System.Reflection;
using System.Security;
using System.ServiceModel;
using VBFTestWCF.Authenticate;

namespace VBFTestWCF
{
    public class CallWcf
    {
        public static SecureString UserId { get; set; }
        public static SecureString UserPassword { get; set; }
        public static SecureString EndPointUrl { get; set; }
        public string LoadConfiguration()
        {
            var fileName = Assembly.GetExecutingAssembly().GetName().Name;
            return fileName;
        }

        public void GetConfigValues(string fileName)
        {
            var dllConfigFile = Environment.CurrentDirectory.Trim() +"\\" + fileName.Trim() + ".dll";

            //Code to pick up the DLL starts here.
            try
            {
                Configuration configuration = ConfigurationManager.OpenExeConfiguration(dllConfigFile);
                
                

                //So far we got the config file for the dll in here.
                var appSettings = configuration.AppSettings.Settings;
                foreach (KeyValueConfigurationElement kvCe in appSettings)
                {
                    kvCe.Value = EncryptString(ToSecureString(kvCe.Value));
                    Console.WriteLine(kvCe.Value);
                }
                

                foreach (KeyValueConfigurationElement keyValueConfigurationElement in appSettings)
                {
                    switch(keyValueConfigurationElement.Key)
                        {
                        case "WSUser": UserId = DecryptString(keyValueConfigurationElement.Value);
                            break;
                        case "WSUserPassword": UserPassword = DecryptString(keyValueConfigurationElement.Value);
                            break;
                        case "endpointurl": EndPointUrl = DecryptString(keyValueConfigurationElement.Value);
                            break;
                            
                        }
                }
                //UserId = DecryptString(appSettings["WSUser"].Value);

                Console.WriteLine(string.Format("User:{0}\t Password:\t{1} \t{2}", ToInsecureString(UserId), ToInsecureString(UserPassword),ToInsecureString(EndPointUrl)));
                

            }
            catch (Exception e)
            {
                Console.WriteLine(e.Message);

            }
        }

        public string GetToken()
        {
            var obj = CreateWebServiceInstance(ToInsecureString(EndPointUrl));
            var retval = obj.AuthenticateWithDetails(ToInsecureString(UserId), ToInsecureString(UserPassword));
            return retval.AuthenticationKey;

        }

        internal static AuthenticateSvcClient CreateWebServiceInstance(string endpointurl)
        {
            var binding = new BasicHttpBinding
                                           {
                                               SendTimeout = TimeSpan.FromMinutes(1),
                                               OpenTimeout = TimeSpan.FromMinutes(1),
                                               CloseTimeout = TimeSpan.FromMinutes(1),
                                               ReceiveTimeout = TimeSpan.FromMinutes(10),
                                               AllowCookies = false,
                                               BypassProxyOnLocal = false,
                                               HostNameComparisonMode = HostNameComparisonMode.StrongWildcard,
                                               MessageEncoding = WSMessageEncoding.Text,
                                               TextEncoding = System.Text.Encoding.UTF8,
                                               TransferMode = TransferMode.Buffered,
                                               UseDefaultWebProxy = true
                                           };
            // I think most (or all) of these are defaults--I just copied them from app.config:

            return new AuthenticateSvcClient(binding, new EndpointAddress((endpointurl)));
        }

        static readonly byte[] Entropy = System.Text.Encoding.Unicode.GetBytes("Salt Is Not A Password");

        public static string EncryptString(SecureString input)
        {
            byte[] encryptedData = System.Security.Cryptography.ProtectedData.Protect(
                System.Text.Encoding.Unicode.GetBytes(ToInsecureString(input)),
                Entropy,
                System.Security.Cryptography.DataProtectionScope.CurrentUser);
            return Convert.ToBase64String(encryptedData);
        }

        public static SecureString DecryptString(string encryptedData)
        {
            try
            {
                byte[] decryptedData = System.Security.Cryptography.ProtectedData.Unprotect(
                    Convert.FromBase64String(encryptedData),
                    Entropy,
                    System.Security.Cryptography.DataProtectionScope.CurrentUser);
                return ToSecureString(System.Text.Encoding.Unicode.GetString(decryptedData));
            }
            catch
            {
                return new SecureString();
            }
        }

        public static SecureString ToSecureString(string input)
        {
            SecureString secure = new SecureString();
            foreach (char c in input)
            {
                secure.AppendChar(c);
            }
            secure.MakeReadOnly();
            return secure;
        }

        public static string ToInsecureString(SecureString input)
        {
            string returnValue = string.Empty;
            IntPtr ptr = System.Runtime.InteropServices.Marshal.SecureStringToBSTR(input);
            try
            {
                returnValue = System.Runtime.InteropServices.Marshal.PtrToStringBSTR(ptr);
            }
            finally
            {
                System.Runtime.InteropServices.Marshal.ZeroFreeBSTR(ptr);
            }
            return returnValue;
        }
    }

}
